package org.hackystat.devcathlon.match;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.devcathlon.event.Event;
import org.hackystat.devcathlon.team.Team;
import org.hackystat.sensorbase.resource.projects.jaxb.Project;

/**
 * A thread-safe singleton class that manages access to the Matches in this system. 
 * @author Philip Johnson
 */
public class MatchManager {
  /** The singleton instance of this class. */
  private static MatchManager theInstance = new MatchManager();
  /** The (match name, match instance) tuples.  */
  private Map<String, Match> names2matches = new HashMap<String, Match>();
  /** The private constructor. */
  private MatchManager() {
    // does nothing at this point; will initialize from database later. 
  }
  
  /**
   * Returns the singleton instance of the MatchManager.
   * @return The MatchManager. 
   */
  public static MatchManager getInstance() {
    return MatchManager.theInstance;
  }
  
  /**
   * Adds a match to the system. Performs validity checking, including determining that the name
   * is unique.  Should also check that teams2projects and events have legal values.
   * Returns the newly created Match instance.  
   * @param name The name of this match
   * @param startDate The startDate.
   * @param endDate The endDate.
   * @param teams2projects A set of (team, project) tuples.
   * @param events A list of events that the teams will compete in. 
   * @return The newly created Match. 
   * @throws MatchException If errors occur during Match creation. 
   */
  public synchronized Match addMatch(String name, XMLGregorianCalendar startDate, 
      XMLGregorianCalendar endDate, Map<Team, Project> teams2projects, List<Event> events) 
      throws MatchException {
    // Ensure that match names are unique. 
    if (this.names2matches.containsKey(name)) {
      throw new MatchException("Attempt to add a match with a pre-existing name: " + name);
    }
    Match match = new Match(name, startDate, endDate, teams2projects, events);
    names2matches.put(name, match);
    return match;
  }
  
  /**
   * Returns the match associated with the name, or null if not found. 
   * @param name The name of the match to be retrieved. 
   * @return The match instance, or null if not found. 
   */
  public synchronized Match getMatch(String name) {
    return this.names2matches.get(name);
  }
  
  /**
   * Ensures that the passed match name is no longer in the set of defined Matches.
   * Does nothing if the match name is not known.
   * @param name The match name.
   */
  public synchronized void deleteMatch(String name) {
    this.names2matches.remove(name);
  }
  
}
